package com.jctrip.hotel.source.service.route2source;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import com.jctrip.hotel.domain.entity.HtSourceInfo;
import com.jctrip.hotel.source.model.elong.ElongLocalEnum;
import com.jctrip.hotel.source.model.elong.req.offline.ElongCancelOrderReq;
import com.jctrip.hotel.source.model.elong.req.offline.ElongCreateOrderReq;
import com.jctrip.hotel.source.model.elong.req.offline.ElongQueryOrderDetailReq;
import com.jctrip.hotel.source.model.greentree.req.*;
import com.jctrip.hotel.source.model.greentree.resp.BookingCheckActivityResp;
import com.jctrip.hotel.source.model.hmein.resp.RoomStatusResult;
import com.jctrip.hotel.source.model.hworld.resp.HworldRoomCountDailyDTO;
import com.jctrip.hotel.source.model.meituan.req.OrderBookingReq;
import com.jctrip.hotel.source.model.meituan.req.OrderCancelReq;
import com.jctrip.hotel.source.model.meituan.req.OrderQueryReq;
import com.jctrip.hotel.source.service.basic.*;
import com.jctrip.hotel.source.service.elong.ElongService;
import com.jctrip.hotel.common.route2source.model.param.Route2SourceCheckPriceAndCountParam;
import com.jctrip.hotel.common.route2source.model.result.Route2SourceCheckPriceAndCountResult;
import com.jctrip.hotel.common.util.*;
import com.jctrip.hotel.domain.entity.HtPriceCalendarRezen;
import com.jctrip.hotel.source.model.CnBooking.resp.ValiadRoomStatusResp;
import com.jctrip.hotel.source.model.atour.resp.RoomInventoryData;
import com.jctrip.hotel.source.model.dossen.DossenCheckPriceAndCountReq;
import com.jctrip.hotel.source.model.dossen.DossenPriceAndCountData;
import com.jctrip.hotel.source.model.greentree.resp.BookingCheckAgreementResp;
import com.jctrip.hotel.source.model.hmein.req.CheckAvailableReq;
import com.jctrip.hotel.source.model.hmein.resp.CheckAvailableResult;
import com.jctrip.hotel.source.model.hworld.req.HworldCheckAvailabilityReq;
import com.jctrip.hotel.source.model.hworld.resp.HworldCheckAvailabilityDTO;
import com.jctrip.hotel.source.model.rezen.req.PostOrderCheckReq;
import com.jctrip.hotel.source.model.rezen.resp.PostOrderCheckDTO;
import com.jctrip.hotel.source.model.rezen.resp.RezenBaseResp;
import com.jctrip.hotel.source.model.wehotel.req.GetHotelRoomStatusResult;
import com.jctrip.hotel.source.model.wehotel.resq.GetHotelRealRoomStatus;
import com.jctrip.hotel.source.service.meituan.MeituanService;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.google.common.collect.Lists;
import com.jctrip.hotel.common.enums.SourceEnum;
import com.jctrip.hotel.common.route2source.model.param.Route2SourceCancelOrderParam;
import com.jctrip.hotel.common.route2source.model.param.Route2SourcePostOrderParam;
import com.jctrip.hotel.common.route2source.model.param.Route2SourceQueryOrderParam;
import com.jctrip.hotel.common.route2source.model.result.Route2SourceCancelOrderResult;
import com.jctrip.hotel.common.route2source.model.result.Route2SourcePostOrderResult;
import com.jctrip.hotel.common.route2source.model.result.Route2SourceQueryOrderResult;
import com.jctrip.hotel.common.route2source.service.Route2SourceOrderService;
import com.jctrip.hotel.domain.entity.HtPriceCalendarCnbe;
import com.jctrip.hotel.domain.entity.HtPriceCalendarGreentree;
import com.jctrip.hotel.source.model.CnBooking.IdentityInfoDTO;
import com.jctrip.hotel.source.model.CnBooking.req.CNBEPostOrderReq;
import com.jctrip.hotel.source.model.CnBooking.req.CNBEPostOrderReq.BookInfo;
import com.jctrip.hotel.source.model.CnBooking.req.CNBEPostOrderReq.GuestInfo;
import com.jctrip.hotel.source.model.OrderDataResult;
import com.jctrip.hotel.source.model.PriceCheckParam;
import com.jctrip.hotel.source.model.atour.req.CancelOrderReq;
import com.jctrip.hotel.source.model.atour.req.CreateOrderReq;
import com.jctrip.hotel.source.model.dossen.DossenAddOrderReq;
import com.jctrip.hotel.source.model.dossen.DossenCancelOrderReq;
import com.jctrip.hotel.source.model.hworld.req.HworldAddOrderReq;
import com.jctrip.hotel.source.model.hworld.req.HworldCancelOrderReq;
import com.jctrip.hotel.source.model.rezen.req.RezenPostOrderReq;
import com.jctrip.hotel.source.model.rezen.req.RezenPostOrderReq.ContactPerson;
import com.jctrip.hotel.source.model.rezen.req.RezenPostOrderReq.RoomRate;
import com.jctrip.hotel.source.model.wehotel.req.OrderData;
import com.jctrip.hotel.source.model.wehotel.resq.CancelOrder;
import com.jctrip.hotel.source.model.wehotel.resq.PostOrder;
import com.jctrip.hotel.source.model.wehotel.resq.QueryOrder;
import com.jctrip.hotel.source.service.CNBooking.CNBookingService;
import com.jctrip.hotel.source.service.atour.AtourService;
import com.jctrip.hotel.source.service.dossen.DossenService;
import com.jctrip.hotel.source.service.greentree.GreenTreeService;
import com.jctrip.hotel.source.service.hmein.HmeinService;
import com.jctrip.hotel.source.service.hworld.HworldService;
import com.jctrip.hotel.source.service.rezen.RezenService;
import com.jctrip.hotel.source.service.wehotel.WeHotelService;

import lombok.extern.slf4j.Slf4j;

/**
 * 渠道请求供应 订单服务
 * <p>
 * route2source的作用：
 * 1、作为适配器，兼容不同供应商的订单参数，面向渠道统一建模
 * 2、management、source、route模块不直接依赖，把接口放在common模块
 */
@Slf4j
@Service
public class Route2SourceOrderServiceImpl implements Route2SourceOrderService {

    @Autowired
    private WeHotelService weHotelService;

    @Autowired
    private AtourService atourService;

    @Autowired
    private DossenService dossenService;

    @Autowired
    private HworldService hworldService;

    @Autowired
    private HmeinService hmeinService;
    @Autowired
    private CNBookingService cnBookingService;
    @Autowired
    private RezenService rezenService;
    @Autowired
    private HtPriceCalendarCnbeService htPriceCalendarCnbeService;
    @Autowired
    private HtPriceCalendarService htPriceCalendarService;
    @Autowired
    private GreenTreeService greenTreeService;
    @Autowired
    private HtPriceCalendarGreentreeService htPriceCalendarGreentreeService;
    @Autowired
    private HtPriceCalendarRezenService htPriceCalendarRezenService;
    @Autowired
    private ElongService elongService;
    @Autowired
    private MeituanService meituanService;
    @Autowired
    private HtSourceInfoService htSourceInfoService;

    @Override
    public Route2SourcePostOrderResult postOrder(Route2SourcePostOrderParam param) {
        SourceEnum sourceEnum = SourceEnum.getByCode(param.getSourceCode());
        if (sourceEnum == null) {
            throw new RuntimeException("无效的sourceCode=" + param.getSourceCode());
        }
        OrderDataResult orderDataResult;
        switch (sourceEnum) {
            case WEHOTEL:
                orderDataResult = weHotelService.postOrder(
                        param.getSourceAppId(),
                        param.getSourceSecret(),
                        PostOrder.builder()
                                .innId(weHotelService.parseHotelId(param.getHotelId()))
                                .roomTypeId(param.getRoomTypeCode())
                                .productCode(param.getProductCode())
                                .roomCount(param.getRoomCount())
                                .dtArrorig(param.getArriveDate())
                                .dtDeporig(param.getDepartDate())
                                .payType(param.getPaymentType())
                                .externalId(param.getBookId())
                                .passengers(Arrays.stream(param.getGuestName().split(","))
                                        .map(e -> PostOrder.Guest.builder()
                                                .guestName(e)
                                                .guestMobile(param.getGuestTel())
                                                .build())
                                        .collect(Collectors.toList())
                                )
                                .lastArrTime(param.getLatestArriveTime())
                                .remarks(param.getOrderNotes())
                                .bookMobile(param.getContactTel())
                                .bookName(param.getContactName())
                                .build(),
                        PriceCheckParam.builder()
                                .totalRate(param.getTotalPrice())
                                .tolerancePrice(param.getTolerancePrice())
                                .raiseFunc(param.getRaiseFunc())
                                .build()
                );
                break;
            case ATOUR:
                orderDataResult = atourService.postOrder(
                        NumberUtils.toInt(param.getSourceAppId()),
                        param.getSourceSecret(),
                        CreateOrderReq.builder()
                                .appId(atourService.parseAppId(param.getSourceAppId()))
                                .hotelId(atourService.parseHotelId(param.getHotelId()))
                                .roomTypeId(atourService.parseRoomTypeId(param.getRoomTypeCode()))
                                .roomNum(param.getRoomCount())
                                .roomRateTypeId(
                                        (Integer) JsonUtil.toMap(param.getSourceExtra()).get("roomRateTypeId")
                                )
                                .arrival(param.getArriveDate())
                                .departure(param.getDepartDate())
                                .mobile(param.getContactTel())
                                .contactName(param.getContactName())
                                .guestName(param.getGuestName())
                                .source(
                                        (Integer) JsonUtil.toMap(param.getSourceExtra()).get("sourceId")
                                )
                                .subSource(
                                        (Integer) JsonUtil.toMap(param.getSourceExtra()).get("subSourceId")
                                )
                                .thirdOrderNo(param.getBookId())
                                .remark(param.getOrderNotes())
                                .mebId(
                                        (Integer) JsonUtil.toMap(param.getSourceExtra()).get("mebId")
                                )
                                .build(),
                        PriceCheckParam.builder()
                                .totalRate(param.getTotalPrice())
                                .tolerancePrice(param.getTolerancePrice())
                                .raiseFunc(param.getRaiseFunc())
                                .build(),
                        param.getSourceExtra()
                );
                break;
            case DOSSEN:
                orderDataResult = dossenService.postOrder(
                        param.getSourceAppId(),
                        param.getSourceSecret(),
                        DossenAddOrderReq.builder()
                                .hotelId(dossenService.parseHotelId(param.getHotelId()))
                                .roomTypeId(param.getRoomTypeCode())
                                //todo 中台yyyy-MM-dd ,东呈改为yyyy-MM-dd HH:mm:ss
                                .checkInDate(param.getArriveDate() + " 00:00:00")
                                .checkOutDate(param.getDepartDate() + " 00:00:00")
                                .activityCode(
                                        (String) JsonUtil.toMap(param.getSourceExtra()).get("activityCode")
                                )
                                .num(param.getRoomCount())
                                .mebName(param.getContactName())
                                .tel(param.getContactTel())
                                .remark(param.getOrderNotes())
                                .checkInType("NS")
                                .isGuarantee(true)
                                .outOrderId(param.getBookId())
                                .otaBookType("1")
                                .enterpriseProtocolCode(
                                        (String) JsonUtil.toMap(param.getSourceExtra()).get("enterpriseProtocolCode")
                                )
                                .build(),
                        PriceCheckParam.builder()
                                .totalRate(param.getTotalPrice())
                                .tolerancePrice(param.getTolerancePrice())
                                .raiseFunc(param.getRaiseFunc())
                                .build()
                );
                break;
            case HWORLD:
                String rateCode = null;
                String activityId = null;

                /**
                 *  如果价格政策表中的活动参数为空， 则取source表中的参数；
                 *  否则，取活动参数解析
                 */
                if (StringUtils.isBlank(param.getPricePolicyExtra())) {
                    rateCode = (String) JsonUtil.toMap(param.getExtra()).get("rateCode");
                } else {
                    rateCode = (String) JsonUtil.toMap(param.getPricePolicyExtra()).get("rateCode");
                    activityId = (String) JsonUtil.toMap(param.getPricePolicyExtra()).get("activityId");
                }

                // 1. 非活动价;2.特定酒店 =》 则特殊处理活动价
                if (StringUtils.isBlank(activityId) && StringUtils.isNotBlank(param.getHotelExtra())) {
                    String hotelRateCode = (String) JsonUtil.toMap(param.getHotelExtra()).get("rateCode");
                    if (!rateCode.endsWith(hotelRateCode)) {
                        rateCode = String.format("%s-%s", rateCode, hotelRateCode);
                    }
                }
                HworldAddOrderReq hworldAddOrderReq = HworldAddOrderReq.builder()
                        .requestNo(param.getBookId())
                        .adults(param.getGuestName().split(",").length)
                        .linkName(param.getContactName())
                        .linkMobile(param.getContactTel())
                        .hotelId(hworldService.parseHotelId(param.getHotelId()))
                        .roomTypeId(param.getRoomTypeCode())
                        // 会员价 和 活动价的担保方式不同
                        .guaranteeMode(StringUtils.isBlank(activityId) ? "FIRST_NIGHT":"FULL_AMOUNT")
                        .rateCode(rateCode) // 特殊处理
                        .checkInDate(DateUtil.parseDate(param.getArriveDate(), "yyyy-MM-dd"))
                        .checkOutDate(DateUtil.parseDate(param.getDepartDate(), "yyyy-MM-dd"))
                        .roomCount(param.getRoomCount())
                        .bookerId(
                                (String) JsonUtil.toMap(param.getSourceExtra()).get("bookId")
                        )
                        .invoiceNo(
                                (String) JsonUtil.toMap(param.getSourceExtra()).get("invoiceNo")
                        )
                        // todo 临时改动
                        .remark("应客户方要求，该合作企业员工电话做保密处理，预定联系人信息为嘉程商旅备用客服电话，也可沟通主客服热线0571-22934358，仅限重要事件沟通，日常确认按订单入住人信息处理即可")
                        .build();
                if (StringUtils.isNotBlank(activityId)) {
                    hworldAddOrderReq.setActivityId(activityId);
                }
                orderDataResult = hworldService.postOrder(
                        param.getSourceAppId(),
                        param.getSourceSecret(),
                        hworldAddOrderReq,
                        PriceCheckParam.builder()
                                .totalRate(param.getTotalPrice())
                                .tolerancePrice(param.getTolerancePrice())
                                .raiseFunc(param.getRaiseFunc())
                                .build()
                );
                break;
            case HMEIN:
                String guestNum = StringUtils.isNotBlank(param.getProductCode()) ? (String) JsonUtil.toMap(param.getProductCode()).get("guestNum") : null;
                orderDataResult = hmeinService.postOrder(
                        com.jctrip.hotel.source.model.hmein.req.CreateOrderReq.builder()
                                .HotelCd(hmeinService.parseHotelId(param.getHotelId()))
                                .RateCode(
                                        (String) JsonUtil.toMap(param.getSourceExtra()).get("rateCode")
                                )
                                .ArrDate(DateUtil.parseDate(param.getArriveDate(), "yyyy-MM-dd"))
                                .DepDate(DateUtil.parseDate(param.getDepartDate(), "yyyy-MM-dd"))
                                .GustName(param.getContactName())
                                .MobileTel(param.getContactTel())
                                .CRSRmType(param.getRoomTypeCode())
                                .RmNum(param.getRoomCount())
//                                .GuestNum(param.getGuestName().split(",").length)
                                // todo 临时修改
                                .GuestNum(StringUtils.isNotBlank(guestNum) ? Integer.parseInt(guestNum) : param.getGuestName().split(",").length)
                                .MemberNo(
                                        (String) JsonUtil.toMap(param.getSourceExtra()).get("memberNo")
                                )
                                .TrustMemberNo(
                                        (String) JsonUtil.toMap(param.getSourceExtra()).get("trustMemberNo")
                                )
                                .GustInfos(Arrays.stream(param.getGuestName().split(","))
                                        .map(e -> com.jctrip.hotel.source.model.hmein.req.CreateOrderReq.GustInfo.builder()
                                                .GustNm(e)
                                                .Phone(param.getGuestTel())
                                                .build())
                                        .collect(Collectors.toList())
                                ).OutOrders(
                                Lists.newArrayList(
                                        com.jctrip.hotel.source.model.hmein.req.CreateOrderReq.OutOrder.builder()
                                                .OutOrderNo(param.getBookId())
                                                .build()
                                ))
                                .Terminal_License(param.getSourceAppId())
                                .LicenseFlag((String) JsonUtil.toMap(param.getSourceExtra()).get("licenseFlag"))
                                // todo 添加早餐数
                                .Count(String.valueOf(param.getBreakfast()))
                                .build(),
                        PriceCheckParam.builder()
                                .totalRate(param.getTotalPrice())
                                .tolerancePrice(param.getTolerancePrice())
                                .raiseFunc(param.getRaiseFunc())
                                .build(),
                        param.getSourceAppId()
                );
                break;
            // todo 龙腾国外酒店处理目前沿用国内酒店
            case CNBEINT:
            case CNBE:
                IdentityInfoDTO infoDTO = IdentityInfoDTO.builder()
                        .appId(param.getSourceAppId())
                        .securityKey(param.getSourceSecret())
                        .userName((String) JsonUtil.toMap(param.getExtra()).get("userName"))
                        .passWord((String) JsonUtil.toMap(param.getExtra()).get("passWord"))
                        .signature((String) JsonUtil.toMap(param.getExtra()).get("signature"))
                        .build();
                List<HtPriceCalendarCnbe> htPriceCalendarCnbes = Optional.ofNullable(
                        htPriceCalendarCnbeService.list(new LambdaQueryWrapper<HtPriceCalendarCnbe>()
                                        .eq(HtPriceCalendarCnbe::getHotelId, param.getHotelId())
                                        .eq(HtPriceCalendarCnbe::getRoomTypeCode, param.getRoomTypeCode())
                                //                        .eq(HtCnbePriceCalendar::getBreakfastCount, param
                                //                        .getBreakfast())
                        ))
                        .orElse(new ArrayList<>());
                if (CollectionUtils.isEmpty(htPriceCalendarCnbes)) {
                    throw new RuntimeException("内部错误");
                }
                //todo 汇率
                BigDecimal priceRate = new BigDecimal("1.00");
                String currency = (String) JsonUtil.toMap(param.getExtra()).get("currency");
                String postCurrency = (String) JsonUtil.toMap(param.getExtra()).get("postCurrency");
                if ("USD".equals(currency)) {
                    String rate = (String) JsonUtil.toMap(param.getExtra()).get("priceRate");
                    if (StringUtils.isBlank(rate)) {
                        throw new RuntimeException("汇率比为空");
                    }
                    priceRate = priceRate.multiply(new BigDecimal(rate));
                }
                CNBEPostOrderReq req = CNBEPostOrderReq.builder()
                        .checkIn(param.getArriveDate())
                        .checkOut(param.getDepartDate())
                        .currency(postCurrency)
                        .orderAmount(String.valueOf(param.getTotalPrice().multiply(priceRate)))
                        .customerOrderId(param.getBookId())
                        .bookInfo(BookInfo.builder().bookName(param.getContactName()).bookPhone(param.getContactTel())
                                .build())
                        .guestInfos(Arrays.stream(param.getGuestName().split(","))
                                .map(e -> GuestInfo.builder()
                                        .guestName(e)
                                        .guestPhone(param.getGuestTel())
                                        .guestType("013001")
                                        .build()).collect(Collectors.toList()))
                        .hotelId(cnBookingService.parseHotelId(param.getHotelId()))
                        .rateplanId(htPriceCalendarCnbes.get(0).getProductId())
                        .roomId(param.getRoomTypeCode())
                        .roomCount(String.valueOf(param.getRoomCount()))
                        .build();
                if (null == req.getRateplanId()) {
                    throw new RuntimeException("无效的rateplan");
                }
                orderDataResult = cnBookingService.postOrder(req, infoDTO, PriceCheckParam.builder()
                        .totalRate(param.getTotalPrice().multiply(priceRate))
                        .tolerancePrice(param.getTolerancePrice())
                        .raiseFunc(param.getRaiseFunc())
                        .build());
                break;
            case REZENCO:
                orderDataResult = rezenService.postOrderByCompany(param.getSourceAppId(), param.getSourceSecret(),
                        RezenPostOrderReq.builder()
                                .companyId(Long.valueOf((String) JsonUtil.toMap(param.getExtra()).get("companyId")))
                                .checkInDate(param.getArriveDate())
                                .checkOutDate(param.getDepartDate())
                                .contactPerson(
                                        ContactPerson.builder()
                                                .firstName(param.getGuestName())
                                                .phone(param.getGuestTel())
                                                .build())
                                .distributorResId(param.getBookId())
                                .groupId(Long.valueOf((String) JsonUtil.toMap(param.getExtra()).get("groupId")))
                                .hotelId(rezenService.parseHotelId3(param.getHotelId()))
                                .roomQuantity(param.getRoomCount())
                                .roomRate(
                                        RoomRate.builder()
                                                .paymentType(1)
                                                .roomtypId(Long.valueOf(param.getRoomTypeCode()))
                                                .productId(Long.valueOf(rezenService.getProductId(param.getHotelId(),
                                                        param.getRoomTypeCode(), param.getSourceId(),
                                                        param.getBreakfast(), 4, param.getArriveDate()))).build())
                                .build(),
                        PriceCheckParam.builder()
                                .totalRate(param.getTotalPrice())
                                .tolerancePrice(param.getTolerancePrice())
                                .raiseFunc(param.getRaiseFunc())
                                .build());
                break;
            case REZEN:
                if (rezenService.checkSourceIdIs2(param.getSourceId())) {
                    // 二方key，走二方下单
                    orderDataResult = rezenService.postOrder(param.getSourceAppId(), param.getSourceSecret(),
                            RezenPostOrderReq.builder().checkInDate(param.getArriveDate())
                                    .checkOutDate(param.getDepartDate())
                                    .contactPerson(
                                            ContactPerson.builder().firstName(param.getGuestName())
                                                    .phone(param.getGuestTel()).build()).distributorResId(param.getBookId())
                                    .groupId(Long.valueOf((String) JsonUtil.toMap(param.getExtra()).get("groupId")))
                                    .hotelId(rezenService.parseHotelId(param.getHotelId()))
                                    .roomQuantity(param.getRoomCount())
                                    .roomRate(
                                            RoomRate.builder().paymentType(1)
                                                    .roomtypId(Long.valueOf(param.getRoomTypeCode()))
                                                    .productId(Long.valueOf(rezenService.getProductId(param.getHotelId(),
                                                            param.getRoomTypeCode(), param.getSourceId(),
                                                            param.getBreakfast(), 4, param.getArriveDate()))).build())
                                    .build(),
                            PriceCheckParam.builder()
                                    .totalRate(param.getTotalPrice())
                                    .tolerancePrice(param.getTolerancePrice())
                                    .raiseFunc(param.getRaiseFunc())
                                    .build());
                } else {
                    // 三方key，走三方下单
                    orderDataResult = rezenService.postOrderByCompany(param.getSourceAppId(), param.getSourceSecret(),
                            RezenPostOrderReq.builder()
                                    .companyId(Long.valueOf((String) JsonUtil.toMap(param.getExtra()).get("companyId")))
                                    .checkInDate(param.getArriveDate())
                                    .checkOutDate(param.getDepartDate())
                                    .contactPerson(
                                            ContactPerson.builder()
                                                    .firstName(param.getGuestName())
                                                    .phone(param.getGuestTel())
                                                    .build())
                                    .distributorResId(param.getBookId())
                                    .groupId(Long.valueOf((String) JsonUtil.toMap(param.getExtra()).get("groupId")))
                                    .hotelId(rezenService.parseHotelId(param.getHotelId()))
                                    .roomQuantity(param.getRoomCount())
                                    .roomRate(
                                            RoomRate.builder()
                                                    .paymentType(1)
                                                    .roomtypId(Long.valueOf(param.getRoomTypeCode()))
                                                    .productId(Long.valueOf(rezenService.getProductId(param.getHotelId(),
                                                            param.getRoomTypeCode(), param.getSourceId(),
                                                            param.getBreakfast(), 4, param.getArriveDate()))).build())
                                    .build(),
                            PriceCheckParam.builder()
                                    .totalRate(param.getTotalPrice())
                                    .tolerancePrice(param.getTolerancePrice())
                                    .raiseFunc(param.getRaiseFunc())
                                    .build());
                }
                break;
            case GREENTREE:
                // 下单时，判断是否存在有活动房型
                String activityCode = null;
                List<HtPriceCalendarGreentree> htPriceCalendarGreentreeList = htPriceCalendarGreentreeService.list(new LambdaQueryWrapper<HtPriceCalendarGreentree>()
                        .eq(HtPriceCalendarGreentree::getHotelId, param.getHotelId())
                        .eq(HtPriceCalendarGreentree::getRoomTypeCode, param.getRoomTypeCode())
                        .between(HtPriceCalendarGreentree::getCalDate, param.getArriveDate(), DateUtil.getYesterday(param.getDepartDate())));
                List<HtPriceCalendarGreentree> activityCalendar = htPriceCalendarGreentreeList.stream()
                        .filter(e -> StringUtils.isNotBlank(e.getRateplanId()) && e.getQuota() > 0
                                && e.getPurchasePrice().compareTo(e.getRetailPrice()) < 0)
                        .collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(activityCalendar) && activityCalendar.size() == DateUtil.countDay(param.getArriveDate(), param.getDepartDate())) {
                    activityCode = activityCalendar.get(0).getRateplanId();
                }

                // 活动价下单
                if (StringUtils.isNotBlank(activityCode)) {
                    CreateBookingActivityReq createBookingReq = CreateBookingActivityReq.builder()
                            .reservationInfo(CreateBookingActivityReq.ReservationInfo.builder()
                                    .agentUniqueID(param.getBookId())  //预订号（中介订单号
                                    .hotelCode(greenTreeService.parseHotelId(param.getHotelId())) //酒店id
                                    .activityCode(activityCode) //房型活动码
                                    .keepTime("18:00") //保留时间，默认18点
                                    .startDate(param.getArriveDate()) // 开始日期
                                    .endDate(param.getDepartDate()) // 结束日期
                                    .guarantee(CreateBookingActivityReq.ReservationInfo.Guarantee.builder()
                                            .guaranteeType("NONE") // 担保
                                            .build())
                                    .reqRooms(CreateBookingActivityReq.ReservationInfo.ReqRooms.builder()
                                            .reqRoom(CreateBookingActivityReq.ReservationInfo.ReqRooms.ReqRoom.builder()
                                                    .roomCount(param.getRoomCount())  // 房间数
                                                    .roomTypeCode(param.getRoomTypeCode()) // 房间编号
                                                    // roomRate参数留在下单环节补全
//                                                    .roomRate(CreateBookingActivityReq.ReservationInfo.ReqRooms.ReqRoom.RoomRate.builder()
//                                                            .price(htPriceCalendarGreentree.getPurchasePrice())
//                                                            .currencyCode("CNY")
//                                                            .build())
                                                    .build())
                                            .build())
                                    .build())
                            .customInfos(CreateBookingActivityReq.CustomInfos.builder()
                                    .customInfo(CreateBookingActivityReq.CustomInfos.CustomInfo.builder()
                                            .contactPhone(Optional.ofNullable(param.getContactTel()).orElse("19812387777"))  // 手机号
                                            .firstName(param.getContactName().substring(1)) // 姓
                                            .lastName(param.getContactName().substring(0, 1)) // 名
                                            .nameTitle("X") //称呼， 先生
                                            .gender("X") //性别
                                            .contactEmail(RandomUtil.createRandomStr(6) + "@qq.com") // 邮箱
                                            .build())
                                    .build())
                            .build();

                    orderDataResult = greenTreeService.postActivityOrder(createBookingReq,
                            PriceCheckParam.builder()
                                    .totalRate(param.getTotalPrice())
                                    .tolerancePrice(param.getTolerancePrice())
                                    .raiseFunc(param.getRaiseFunc())
                                    .build(),
                            param.getBreakfast(),
                            param.getBookId());
                    log.info("活动价下单,平台订单号:{}, 供应订单号 : {}", orderDataResult.getOrderCode(), orderDataResult.getExternalId());
                } else {
                    // 协议价下单
                    CreateBookingAgreementReq createBookingReq = CreateBookingAgreementReq.builder()
                            .reservationInfo(CreateBookingAgreementReq.ReservationInfo.builder()
                                    .agentUniqueID(param.getBookId())  //预订号（中介订单号
                                    .agentAgreementNo((String) JsonUtil.toMap(param.getSourceExtra()).get("AgentAgreementNo")) //协议号
                                    .hotelCode(greenTreeService.parseHotelId(param.getHotelId())) //酒店id
                                    .keepTime("18:00") //保留时间，默认18点
                                    .comment(String.format(
                                            "|费用总计:%.2f|含早情况：%d,房费由嘉程商旅支付,杂费客人自理，渠道开具发票，嘉程商旅订单号:%s 嘉程商旅客服电话：%s，价格保密",
                                            param.getTotalPrice(),
                                            param.getBreakfast(),
                                            param.getBookId(),
                                            "0571-22934358")) //备注,|费用总计:xx|，必须填写
                                    .startDate(param.getArriveDate()) // 开始日期
                                    .endDate(param.getDepartDate()) // 结束日期
                                    .guarantee(CreateBookingAgreementReq.Guarantee.builder()
                                            .guaranteeType("NONE") // 担保
                                            .build())
                                    .reqRooms(CreateBookingAgreementReq.ReqRooms.builder()
                                            .reqRoom(CreateBookingAgreementReq.ReqRoom.builder()
                                                    .roomCount(param.getRoomCount())  // 房间数
                                                    .roomTypeCode(param.getRoomTypeCode()) // 房间编号
                                                    // roomRate参数留在下单环节补全
//                                                    .agreeRate(CreateBookingAgreementReq.AgreeRate.builder()
//                                                            .price(htPriceCalendarGreentree.getPurchasePrice()) //房间首晚价格
//                                                            .currencyCode("CNY") // 币种类型
//                                                            .build())
                                                    .build())
                                            .build())
                                    .build())
                            .customInfos(CreateBookingAgreementReq.CustomInfos.builder()
                                    .customInfo(CreateBookingAgreementReq.CustomInfo.builder()
                                            .contactPhone(Optional.ofNullable(param.getContactTel()).orElse("19812387777"))  // 手机号
                                            .firstName(param.getContactName().substring(1)) // 姓
                                            .lastName(param.getContactName().substring(0, 1)) // 名
                                            .nameTitle("X") //称呼， 先生
                                            .gender("X") //性别
                                            .contactEmail(RandomUtil.createRandomStr(6) + "@qq.com") // 邮箱
                                            .build())
                                    .build())
                            .build();
                    createBookingReq.setChainCode(param.getSourceAppId());

                    orderDataResult = greenTreeService.postAgreementOrder(createBookingReq,
                            PriceCheckParam.builder()
                                    .totalRate(param.getTotalPrice())
                                    .tolerancePrice(param.getTolerancePrice())
                                    .raiseFunc(param.getRaiseFunc())
                                    .build(),
                            param.getBreakfast(),
                            param.getBookId());
                    log.info("协议价下单,平台订单号:{}, 供应订单号 : {}", orderDataResult.getOrderCode(), orderDataResult.getExternalId());
                }
                break;
            case ELONGDOM:
                ElongCreateOrderReq orderReq = null;
                try {
                    List<ElongCreateOrderReq.Customer> customers = Lists.newArrayList(param.getGuestName().split(","))
                            .stream()
                            .map(e -> ElongCreateOrderReq.Customer.builder()
                                    .name(e)
                                    .gender("Unknown")
                                    .nationality("中国")
                                    .build()).collect(Collectors.toList());
                    List<ElongCreateOrderReq.OrderRoom> orderRooms = new ArrayList<>();
                    // 需要分成几间
                    int size = customers.size() / param.getRoomCount();
                    int length = customers.size();
                    for (int i = 0; i < param.getRoomCount(); i++) {
                        orderRooms.add(ElongCreateOrderReq.OrderRoom.builder()
                                .customers(customers.subList(i * size, i != param.getRoomCount() - 1 ? (i + 1) * size : length))
                                .build());
                    }
                    String[] info = elongService.getPostInfo(param.getHotelId(), param.getRoomTypeCode(), param.getSourceId(), param.getProductCode());
                    orderReq = ElongCreateOrderReq.builder()
                            .affiliateConfirmationId(param.getBookId())
                            .hotelId(elongService.parseHotelId(param.getHotelId()))
                            .roomId(param.getRoomTypeCode())
                            .roomTypeId(info[0])
                            .ratePlanId(Integer.valueOf(info[1]))
                            .hotelCode(info[2])
                            .arrivalDate(new SimpleDateFormat("yyyy-MM-dd").parse(param.getArriveDate()))
                            .departureDate(new SimpleDateFormat("yyyy-MM-dd").parse(param.getDepartDate()))
                            .paymentType(ElongLocalEnum.PREPAY.getCode())
                            .numberOfRooms(param.getRoomCount())
                            .numberOfCustomers(param.getGuestName().split(",").length)
                            .earliestArrivalTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
                                    .parse(String.format("%s 14:00:00", param.getArriveDate())))
                            .latestArrivalTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
                                    .parse(param.getLatestArriveTime()))
                            // ip地址需要提供客人ip 目前没有ip 默认走第一台服务器
                            .customerIPAddress("120.55.103.238")
                            .isGuaranteeOrCharged(true)
                            .confirmationType(ElongLocalEnum.NOTALLOWEDCONFIRM.getCode())
                            .orderRooms(orderRooms)
                            .contact(ElongCreateOrderReq.Contact.builder()
                                    .name(param.getContactName())
                                    .mobile(param.getContactTel())
                                    .gender("Unknown")
                                    .build())
                            .isCreateOrderOnly(false)
                            .build();
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                HtSourceInfo sourceInfo = htSourceInfoService.getOne(new LambdaQueryWrapper<HtSourceInfo>()
                        .eq(HtSourceInfo::getSourceId, param.getSourceId()));
                orderDataResult = elongService.postOrder(
                        (String) JsonUtil.toMap(sourceInfo.getExtra()).get("user"),
                        sourceInfo.getSourceAppId(), sourceInfo.getSourceSecret(),
                        (String) JsonUtil.toMap(sourceInfo.getExtra()).get("local"), orderReq,
                        PriceCheckParam.builder()
                                .totalRate(param.getTotalPrice())
                                .tolerancePrice(param.getTolerancePrice())
                                .raiseFunc(param.getRaiseFunc())
                                .build());
                break;
            case MTHDOM:
                String signature = (String) JsonUtil.toMap(param.getSourceExtra()).get("signature");
                String goodsId = meituanService.getProduct(param.getHotelId(), param.getRoomTypeCode(), param.getSourceId());
                orderDataResult = meituanService.postOrder(OrderBookingReq.builder()
                                .hotelId(Long.valueOf(meituanService.parseHotelId(param.getHotelId())))
                                .goodsId(Long.valueOf(goodsId))
                                .personNames(param.getGuestName())
                                .contactName(param.getContactName())
                                .contactPhone(param.getContactTel())
                                .arriveDate(param.getLatestArriveTime())
                                .checkinDate(param.getArriveDate())
                                .checkoutDate(param.getDepartDate())
                                .roomNum(param.getRoomCount())
                                .totalPrice(param.getTotalPrice().multiply(new BigDecimal("100")).intValue())
                                .distributorOrderId(param.getBookId())
                                .needInvoice(1)
                                .build(),
                        Integer.valueOf(param.getSourceAppId()),
                        param.getSourceSecret(),
                        signature,
                        PriceCheckParam.builder()
                                .totalRate(param.getTotalPrice())
                                .tolerancePrice(param.getTolerancePrice())
                                .raiseFunc(param.getRaiseFunc())
                                .build());
                break;
            default:
                throw new RuntimeException("无效的sourceCode=" + param.getSourceCode());
        }
        return Route2SourcePostOrderResult.builder()
                .bookId(param.getBookId())
                .sourceOrderId(orderDataResult.getOrderCode())
                .sourceOrderStatus(orderDataResult.getOrderState())
                .purchasePrice(orderDataResult.getTotalRate())
                .requestBody(orderDataResult.getRequestJsonStr())
                .responseBody(orderDataResult.getResponseJsonStr())
                .build();
    }

    @Override
    public Route2SourceCancelOrderResult cancelOrder(Route2SourceCancelOrderParam param) {
        SourceEnum sourceEnum = SourceEnum.getByCode(param.getSourceCode());
        if (sourceEnum == null) {
            throw new RuntimeException("无效的sourceCode=" + param.getSourceCode());
        }
        switch (sourceEnum) {
            case WEHOTEL:
                weHotelService.cancelOrder(
                        param.getSourceAppId(),
                        param.getSourceSecret(),
                        CancelOrder.builder()
                                .jsonOrderID(param.getSourceOrderId())
                                .externalId(param.getBookId())
                                .build()
                );
                break;
            case ATOUR:
                atourService.cancelOrder(
                        NumberUtils.toInt(param.getSourceAppId()),
                        param.getSourceSecret(),
                        CancelOrderReq.builder()
                                .appId(atourService.parseAppId(param.getSourceAppId()))
                                .orderNo(param.getBookId())
                                .atourOrderNo(param.getSourceOrderId())
                                .build()
                );
                break;
            case DOSSEN:
                dossenService.cancelOrder(
                        param.getSourceAppId(),
                        param.getSourceSecret(),
                        DossenCancelOrderReq.builder()
                                .resvId(param.getSourceOrderId())
                                .build()
                );
                break;
            case HWORLD:
                hworldService.cancelOrder(
                        param.getSourceAppId(),
                        param.getSourceSecret(),
                        HworldCancelOrderReq.builder()
                                .outTradeId(param.getSourceOrderId())
                                .hotelId(hworldService.parseHotelId(param.getHotelId()))
                                .build()
                );
                break;
            case HMEIN:
                hmeinService.cancelOrder(
                        param.getSourceAppId(),
                        param.getSourceOrderId()
                );
                break;
            // todo 龙腾国外酒店处理目前沿用国内酒店
            case CNBEINT:
            case CNBE:
                IdentityInfoDTO infoDTO = IdentityInfoDTO.builder()
                        .appId(param.getSourceAppId())
                        .securityKey(param.getSourceSecret())
                        .userName((String) JsonUtil.toMap(param.getExtra()).get("userName"))
                        .passWord((String) JsonUtil.toMap(param.getExtra()).get("passWord"))
                        .signature((String) JsonUtil.toMap(param.getExtra()).get("signature"))
                        .build();
                cnBookingService.cancelOrder(infoDTO, param.getSourceOrderId());
                break;
            //todo 丽呈3方取消订单和二方一致
            case REZENCO:
            case REZEN:
                rezenService.cancelOrder(param.getSourceAppId(), param.getSourceSecret(),
                        Long.valueOf((String) JsonUtil.toMap(param.getExtra()).get("groupId")),
                        Long.valueOf(param.getSourceOrderId()),
                        param.getBookId());
                break;
            case GREENTREE:
                CancelBookingReq cancelBookingReq = CancelBookingReq.builder()
                        .hotelCode(greenTreeService.parseHotelId(param.getHotelId()))
                        .uniqueID(param.getSourceOrderId())
                        .cancelTerm(CancelBookingReq.CancelTerm.builder()
                                .cancelType("Cancel")
                                .cancelText("行程改变。")
                                .build())
                        .build();
                cancelBookingReq.setChainCode(param.getSourceAppId());
                greenTreeService.cancelBooking(cancelBookingReq);
                break;
            case ELONGDOM:
                elongService.cancelOrder((String) JsonUtil.toMap(param.getExtra()).get("user"),
                        param.getSourceAppId(), param.getSourceSecret(),
                        (String) JsonUtil.toMap(param.getExtra()).get("local"),
                        ElongCancelOrderReq.builder()
                                .orderId(Long.valueOf(param.getSourceOrderId()))
                                .cancelCode("行程变更")
                                .penaltyAmount(new BigDecimal("-1"))
                                .build());
                break;
            case MTHDOM:
                String signature = (String) JsonUtil.toMap(param.getExtra()).get("signature");
                meituanService.cancelOrder(OrderCancelReq.builder()
                                .distributorOrderId(param.getBookId())
                                .mtOrderId(Long.valueOf(param.getSourceOrderId()))
                                .cancelCheck(0)
                                .cancelReason("行程变更")
                                .build(),
                        Integer.valueOf(param.getSourceAppId()),
                        param.getSourceSecret(),
                        signature);
                break;
            default:
                throw new RuntimeException("无效的sourceCode=" + param.getSourceCode());
        }
        return Route2SourceCancelOrderResult.builder().build();
    }

    @Override
    public Route2SourceQueryOrderResult queryOrder(Route2SourceQueryOrderParam param) {
        SourceEnum sourceEnum = SourceEnum.getByCode(param.getSourceCode());
        if (sourceEnum == null) {
            throw new RuntimeException("无效的sourceCode=" + param.getSourceCode());
        }
        /*
         * 新服务和老服务订单字段梳理：
         * 老服务orderSn/id == 新服务bookId
         * 老服务orderCode == 新服务sourceOrderId
         */
        OrderData orderData;
        switch (sourceEnum) {
            case WEHOTEL:
                orderData = weHotelService.queryOrder(
                        param.getSourceAppId(),
                        param.getSourceSecret(),
                        QueryOrder.builder()
                                .jsonOrderID(param.getSourceOrderId())
                                .externalId(param.getBookId())
                                .build()
                );
                break;
            case ATOUR:
                orderData = atourService.queryOrderData(
                        NumberUtils.toInt(param.getSourceAppId()),
                        param.getSourceSecret(),
                        param.getSourceOrderId(),
                        param.getBookId()
                );
                break;
            case DOSSEN:
                orderData = dossenService.queryOrderData(
                        param.getSourceAppId(),
                        param.getSourceSecret(),
                        param.getSourceOrderId(),
                        param.getBookId()
                );
                break;
            case HWORLD:
                orderData = hworldService.queryOrderData(
                        param.getSourceAppId(),
                        param.getSourceSecret(),
                        param.getBookId()
                );
                break;
            case HMEIN:
                orderData = hmeinService.queryOrderData(
                        param.getSourceAppId(),
                        param.getSourceOrderId(),
                        param.getBookId()
                );
                break;
            // todo 龙腾国外酒店处理目前沿用国内酒店
            case CNBEINT:
            case CNBE:
                IdentityInfoDTO infoDTO = IdentityInfoDTO.builder()
                        .appId(param.getSourceAppId())
                        .securityKey(param.getSourceSecret())
                        .userName((String) JsonUtil.toMap(param.getExtra()).get("userName"))
                        .passWord((String) JsonUtil.toMap(param.getExtra()).get("passWord"))
                        .signature((String) JsonUtil.toMap(param.getExtra()).get("signature"))
                        .build();
                orderData = cnBookingService.queryOrder(infoDTO, param.getSourceOrderId(), param.getBookId());
                break;
            //todo 丽呈3方获取订单和二方一致
            case REZENCO:
            case REZEN:
                orderData = rezenService.getOrderStatus(param.getSourceAppId(), param.getSourceSecret(),
                        Long.valueOf((String) JsonUtil.toMap(param.getExtra()).get("groupId")), param.getBookId());
                break;

            case GREENTREE:
                SearchBookingReq searchBookingReq = SearchBookingReq.builder()
                        .agentUniqueID(param.getBookId())
                        .uniqueID(param.getSourceOrderId())
                        .hotelCode(greenTreeService.parseHotelId(param.getHotelId()))
                        .build();
                searchBookingReq.setChainCode(param.getSourceAppId());
                orderData = greenTreeService.queryOrderData(searchBookingReq);
                break;
            case ELONGDOM:
                orderData = elongService.queryOrderStatus((String) JsonUtil.toMap(param.getExtra()).get("user"),
                        param.getSourceAppId(), param.getSourceSecret(),
                        (String) JsonUtil.toMap(param.getExtra()).get("local"), ElongQueryOrderDetailReq.builder()
                                .affiliateConfirmationId(param.getBookId())
                                .orderId(param.getSourceOrderId() != null ? Long.parseLong(param.getSourceOrderId()) : 0)
                                .build());
                break;
            case MTHDOM:
                String signature = (String) JsonUtil.toMap(param.getExtra()).get("signature");
                orderData = meituanService.queryOrder(OrderQueryReq.builder()
                                .queryParams(Lists.newArrayList(OrderQueryReq.QueryParam.builder()
                                        .distributorOrderId(param.getBookId())
                                        .mtOrderId(Long.valueOf(param.getSourceOrderId()))
                                        .build()))
                                .build(),
                        Integer.valueOf(param.getSourceAppId()),
                        param.getSourceSecret(),
                        signature);
                break;
            default:
                throw new RuntimeException("无效的sourceCode=" + param.getSourceCode());
        }
        return Route2SourceQueryOrderResult.builder()
                .sourceOrderStatus(orderData.getOrderState())
                .build();
    }

    @Override
    public Route2SourceCheckPriceAndCountResult checkPriceAndCount(Route2SourceCheckPriceAndCountParam param) {
        SourceEnum sourceEnum = SourceEnum.getByCode(param.getSourceCode());
        if (sourceEnum == null) {
            throw new RuntimeException("无效的sourceCode=" + param.getSourceCode());
        }
        // 离店日期,日期型和字符串型 yyyy-MM-dd
        Date checkOutDate = DateUtils.addDays(DateUtil.parseDate(param.getBeginDate(), "yyyy-MM-dd"), param.getDays());
        String checkOutString = new SimpleDateFormat("yyyy-MM-dd").format(checkOutDate);

        // todo 修正返回信息，目前只更新了 锦江，华住，如家校验接口，其他品牌后续更新
        // 错误信息
        String errorMsg = "";
        // 实时房态信息
        List<Route2SourceCheckPriceAndCountResult.PriceCalendarBean> priceCalendarBeanList = new ArrayList<>();
        // 房态校验是否失败
        Boolean failFlag = false;
        switch (sourceEnum) {
            case WEHOTEL:
                /**
                 *  房间数和价格在接口请求中均无校验，
                 */
                // 遍历所有价格码
                List<String> productCodeList = JsonUtil.toList(String.class, param.getProductCode());
                GetHotelRealRoomStatus hotelRealRoomStatus = null;
                AtomicReference<Integer> roomCountMinn = new AtomicReference<>(Integer.MAX_VALUE);
                AtomicReference<BigDecimal> totalPriceWehotel = new AtomicReference<>(new BigDecimal(0));
                AtomicReference<BigDecimal> raisedTotalPriceWehotel = new AtomicReference<>(new BigDecimal(0));
                for (String productCode : Optional.ofNullable(productCodeList)
                        .orElseThrow(() -> new RuntimeException("房价码不能为空"))) {
                    try {
                        hotelRealRoomStatus = new GetHotelRealRoomStatus();
                        hotelRealRoomStatus.setInnId(weHotelService.parseHotelId(param.getHotelId()));
                        hotelRealRoomStatus.setRoomTypeCode(param.getRoomTypeCode());
                        hotelRealRoomStatus.setDays(param.getDays());
                        hotelRealRoomStatus.setEndOfDay(param.getBeginDate());
                        hotelRealRoomStatus.setProductCode(productCode);
                        GetHotelRoomStatusResult hotelRealRoomStatusResult = weHotelService.getHotelRealRoomStatusResult(param.getSourceAppId(),
                                param.getSourceSecret(), hotelRealRoomStatus);

                        if (hotelRealRoomStatusResult == null) {
                            continue;
                        }
                        Optional.ofNullable(hotelRealRoomStatusResult.getRoomTypeList()).orElse(new ArrayList<>())
                                .forEach(roomTypeInfo -> {
                                    roomTypeInfo.getProductList().forEach(productData -> {
                                        // 时间得到的是时间戳，转换成yyyy-MM-dd
                                        String calDay = new SimpleDateFormat("yyyy-MM-dd").format(new Date(productData.getEndOfDay()));
                                        // 填充实时房态
                                        priceCalendarBeanList.add(Route2SourceCheckPriceAndCountResult.PriceCalendarBean.builder()
                                                .effectDate(calDay)
                                                .quota(productData.getQuota())
                                                .retailPrice(productData.getRackRate())
                                                .purchasePrice(productData.getAdvanceRate())
                                                .build());

                                        roomCountMinn.set(Math.min(roomCountMinn.get(), productData.getQuota()));
                                        totalPriceWehotel.set(
                                                totalPriceWehotel.get().add(productData.getAdvanceRate()));
                                        raisedTotalPriceWehotel.set(
                                                raisedTotalPriceWehotel.get()
                                                        .add(param.getRaiseFunc().apply(productData.getAdvanceRate())));
                                    });
                                });
                        if (totalPriceWehotel.get().compareTo(BigDecimal.ZERO) > 0
                                && raisedTotalPriceWehotel.get().compareTo(BigDecimal.ZERO) > 0) {
                            break;
                        }

                    } catch (Exception e) {
                        failFlag = true;
                        errorMsg = e.getMessage();
                        log.error("下单校验接口异常：", e);
                    }
                }
                if (hotelRealRoomStatus == null) {
                    throw new RuntimeException("酒店房态信息为空");
                }
                if (Objects.nonNull(param.getRoomCount()) && param.getRoomCount() > roomCountMinn.get()) {
                    failFlag = true;
                    errorMsg = "库存不足";
                }
                if (Objects.nonNull(param.getTotalPrice()) && Objects.nonNull(param.getRoomCount())
                        && param.getTotalPrice().compareTo(totalPriceWehotel.get().multiply(BigDecimal.valueOf(param.getRoomCount()))
                        .subtract(param.getTolerancePrice())) < 0) {
                    log.error("订单销售价不能低于采购总价，订单销售价={}，采购总价={}, 容差金额={}",
                            param.getTotalPrice(), totalPriceWehotel.get().multiply(BigDecimal.valueOf(param.getRoomCount())),
                            param.getTolerancePrice());
                    failFlag = true;
                    errorMsg = "房价变动";
                }


                break;
            case ATOUR:
                /**
                 *  无价格校验接口，查询实时房价和库存进行判断
                 */
                // 实时库存判断
                List<RoomInventoryData> roomInventorys = atourService.getRoomInventoryList(Integer.parseInt(param.getSourceAppId()),
                        param.getSourceSecret(),
                        atourService.parseHotelId(param.getHotelId()),
                        Integer.parseInt(param.getRoomTypeCode()),
                        param.getBeginDate(),
                        checkOutString,
                        (Integer) JsonUtil.toMap(param.getExtra()).get("roomRateTypeId"),
                        (Integer) JsonUtil.toMap(param.getExtra()).get("mebId")
                );
                if (CollectionUtils.isEmpty(roomInventorys)) {
                    throw new RuntimeException("亚朵库存为空，房型下架或禁售");
                }
                Integer roomCountMin = Integer.MAX_VALUE;
                for (RoomInventoryData roomInventory : roomInventorys) {
                    // 会读取到结束日期的数据，不需要
                    if (!roomInventory.getAccDate().equals(checkOutString)) {
                        roomCountMin = Math.min(roomCountMin, roomInventory.getInventoryNum());
                    }
                }
                if (param.getRoomCount() > roomCountMin) {
                    errorMsg = "库存不足";
                    failFlag = true;
                }

                // 实时房价判断
                List<CreateOrderReq.RoomRate> roomRates = atourService.roomRateList(Integer.parseInt(param.getSourceAppId()),
                        param.getSourceSecret(),
                        atourService.parseHotelId(param.getHotelId()),
                        Integer.parseInt(param.getRoomTypeCode()),
                        param.getBeginDate(),
                        checkOutString,
                        (Integer) JsonUtil.toMap(param.getExtra()).get("roomRateTypeId"),
                        (Integer) JsonUtil.toMap(param.getExtra()).get("mebId")
                );
                if (CollectionUtils.isEmpty(roomRates)) {
                    throw new RuntimeException("亚朵房态为空，房型下架或禁售");
                }
                // 价格校验
                BigDecimal totalPriceAtour = BigDecimal.ZERO;
                BigDecimal raisedTotalPriceAtour = BigDecimal.valueOf(0);
                for (CreateOrderReq.RoomRate roomRate : roomRates) {
                    if (!roomRate.getAccDate().equals(checkOutString)) {
                        raisedTotalPriceAtour = raisedTotalPriceAtour.add(
                                param.getRaiseFunc().apply(BigDecimal.valueOf(roomRate.getRoomRate())));
                        totalPriceAtour = totalPriceAtour.add(BigDecimal.valueOf(roomRate.getRoomRate()));
                    }
                }
                if (param.getTotalPrice().compareTo(totalPriceAtour.multiply(BigDecimal.valueOf(param.getRoomCount()))
                        .subtract(param.getTolerancePrice())) < 0) {
                    log.error("订单销售价不能低于采购总价，订单销售价={}，采购总价={}, 容差金额={}",
                            param.getTotalPrice(), totalPriceAtour.multiply(BigDecimal.valueOf(param.getRoomCount())),
                            param.getTolerancePrice());
                    errorMsg = "房价变动";
                    failFlag = true;
                }

                break;
            case DOSSEN:
                /**
                 *  房间数在接口请求中已校验，价格无校验
                 */
                DossenCheckPriceAndCountReq checkPriceAndCountReq = DossenCheckPriceAndCountReq.builder()
                        .checkInDate(param.getBeginDate() + " 00:00:00")
                        .checkOutDate(checkOutString + " 00:00:00")
                        .num(param.getRoomCount())
                        .roomTypeId(param.getRoomTypeCode())
                        .hotelId(dossenService.parseHotelId(param.getHotelId()))
                        .activityCode((String) JsonUtil.toMap(param.getExtra()).get("activityCode"))
                        .enterpriseProtocolCode((String) JsonUtil.toMap(param.getExtra()).get("enterpriseProtocolCode"))
                        .build();
                List<DossenPriceAndCountData> dossenPriceAndCountData = dossenService.checkPriceAndCount(param.getSourceAppId(),
                        param.getSourceSecret(), checkPriceAndCountReq);
                if (dossenPriceAndCountData.size() == 0) {
                    throw new RuntimeException("东呈价格校验，获取房态信息为空");
                }
                // 价格校验
                BigDecimal totalPriceDossen = BigDecimal.ZERO;
                BigDecimal raisedTotalPriceDossen = BigDecimal.valueOf(0);
                for (DossenPriceAndCountData priceAndCountData : Optional.of(dossenPriceAndCountData)
                        .orElseThrow(() -> new RuntimeException("获取房态信息失败"))) {
                    DossenPriceAndCountData.ActivityResvRoomDTO activityResvRoomDTO = new DossenPriceAndCountData.ActivityResvRoomDTO();

                    if (StringUtils.isBlank(checkPriceAndCountReq.getActivityCode())) {
                        BeanUtil.copyProperties(priceAndCountData, activityResvRoomDTO);
                    } else {
                        activityResvRoomDTO =
                                Optional.ofNullable(priceAndCountData.getActivityResvRoomList()).orElse(new ArrayList<>())
                                        .stream()
                                        .filter(dto -> StringUtils.isNotBlank(checkPriceAndCountReq.getActivityCode())
                                                && checkPriceAndCountReq.getActivityCode().equals(dto.getActivityCode()))
                                        .findFirst()
                                        .orElse(null);
                        if (activityResvRoomDTO == null) {
                            BeanUtil.copyProperties(priceAndCountData, activityResvRoomDTO);
                        }
                    }
                    BigDecimal advanceRate = activityResvRoomDTO.getRoomPrice();
                    totalPriceDossen = totalPriceDossen.add(advanceRate);
                    raisedTotalPriceDossen = raisedTotalPriceDossen.add(param.getRaiseFunc().apply(advanceRate));
                }
                if (param.getTotalPrice().compareTo(totalPriceDossen.multiply(BigDecimal.valueOf(param.getRoomCount()))
                        .subtract(param.getTolerancePrice())) < 0) {
                    log.error("订单销售价不能低于采购总价，订单销售价={}，采购总价={}, 容差金额={}",
                            param.getTotalPrice(), totalPriceDossen.multiply(BigDecimal.valueOf(param.getRoomCount())),
                            param.getTolerancePrice());
                    errorMsg = "房价变动";
                    failFlag = true;
                }

                break;
            case HWORLD:
                /**
                 *  房间数和价格在接口请求中均无校验，
                 */
                String activityId = null;
                String rateCode = null;
                if (StringUtils.isNotBlank(param.getPricePolicyExtra())) {
                    rateCode = (String) JsonUtil.toMap(param.getPricePolicyExtra()).get("rateCode");
                    activityId = (String) JsonUtil.toMap(param.getPricePolicyExtra()).get("activityId");
                }
                if (StringUtils.isBlank(rateCode)) {
                    rateCode = (String) JsonUtil.toMap(param.getExtra()).get("rateCode");
                }
                if (StringUtils.isBlank(activityId) && StringUtils.isNotBlank(param.getHotelExtra())) {
                    String hotelRateCode = (String) JsonUtil.toMap(param.getHotelExtra()).get("rateCode");
                    if (!rateCode.endsWith(hotelRateCode)) {
                        rateCode = String.format("%s-%s", rateCode, hotelRateCode);
                    }
                }
                HworldCheckAvailabilityReq hworldCheckAvailabilityReq = HworldCheckAvailabilityReq.builder()
                        .hotelId(hworldService.parseHotelId(param.getHotelId()))
                        .roomTypeId(param.getRoomTypeCode())
                        .checkInDate(DateUtil.parseDate(param.getBeginDate(), "yyyy-MM-dd"))
                        .checkOutDate(checkOutDate)
                        .rateCode(rateCode)
                        .guaranteeMode(StringUtils.isBlank(activityId) ? "FIRST_NIGHT":"FULL_AMOUNT")
                        .bookerId((String) JsonUtil.toMap(param.getExtra()).get("bookId"))
                        .activityId(activityId)
                        .build();
                HworldCheckAvailabilityDTO hworldCheckAvailabilityDTO = hworldService.checkAvailability(param.getSourceAppId(),
                        param.getSourceSecret(), hworldCheckAvailabilityReq);
                // 对反回空值进行处理
                if (hworldCheckAvailabilityDTO == null) {
                    throw new RuntimeException("华住价格校验，接口校验查询失败");
                }
                // 房量校验，返回的是日期区间内的最低房间数
                if (param.getRoomCount() > hworldCheckAvailabilityDTO.getRoomCount().getAvailableCount()) {
                    failFlag = true;
                    errorMsg = "房量不足";
                }

                // 价格校验
                AtomicReference<BigDecimal> hworldtotalRate = new AtomicReference<>(BigDecimal.ZERO);
                AtomicReference<BigDecimal> raisedTotalPrice = new AtomicReference<>(BigDecimal.ZERO);
                hworldCheckAvailabilityDTO.getPriceDailyList().forEach(priceDailyDTO -> {

                    // 填充实时房态
                    HworldRoomCountDailyDTO hworldRoomCountDailyDTO = hworldCheckAvailabilityDTO.getRoomCountDailyList().stream()
                            .filter(e -> e.getBizDate().equals(priceDailyDTO.getBizDate()))
                            .findFirst().orElse(null);
                    Integer quotas = hworldRoomCountDailyDTO == null ? 0 : hworldRoomCountDailyDTO.getAvailableCount();
                    priceCalendarBeanList.add(Route2SourceCheckPriceAndCountResult.PriceCalendarBean.builder()
                            .effectDate(new SimpleDateFormat("yyyy-MM-dd").format(priceDailyDTO.getBizDate()))
                            .quota(quotas)
                            .purchasePrice(priceDailyDTO.getCompanyToGroupPrice())
                            .retailPrice(priceDailyDTO.getMarketPrice())
                            .build());

                    hworldtotalRate.set(hworldtotalRate.get().add(priceDailyDTO.getCompanyToGroupPrice()));
                    raisedTotalPrice.set(raisedTotalPrice.get()
                            .add(param.getRaiseFunc().apply(priceDailyDTO.getCompanyToGroupPrice())));
                });
                if (param.getTotalPrice().compareTo(hworldtotalRate.get().multiply(BigDecimal.valueOf(param.getRoomCount()))
                        .subtract(param.getTolerancePrice())) < 0) {
                    log.error("订单销售价不能低于采购总价，订单销售价={}，采购总价={}, 容差金额={}",
                            param.getTotalPrice(), hworldtotalRate.get().multiply(BigDecimal.valueOf(param.getRoomCount())),
                            param.getTolerancePrice());
                    failFlag = true;
                    errorMsg = "房价变动";
                }

                break;
            case HMEIN:
                /**
                 *  房间数在接口请求中已校验，价格无校验
                 */
                CheckAvailableReq checkAvailableReq = new CheckAvailableReq();
                checkAvailableReq.setHotelCd(hmeinService.parseHotelId(param.getHotelId()));
                checkAvailableReq.setRateCode(param.getProductCode());
                checkAvailableReq.setArrDate(DateUtil.parseDate(param.getBeginDate(), "yyyy-MM-dd"));
                checkAvailableReq.setDepDate(checkOutDate);
                checkAvailableReq.setCRSRmType(param.getRoomTypeCode());
                checkAvailableReq.setRmNum(param.getRoomCount());
                checkAvailableReq.setMemberNo((String) JsonUtil.toMap(param.getExtra()).get("memberNo"));
                checkAvailableReq.setTerminal_License(param.getSourceAppId());
                checkAvailableReq.setTrustMemberNo((String) JsonUtil.toMap(param.getExtra()).get("trustMemberNo"));

                CheckAvailableResult checkAvailableResult = hmeinService.checkAvailability(checkAvailableReq);

                // 获取门市价列表
                List<RoomStatusResult.RoomRateDetailDailys> retailPriceList = hmeinService.getRetailPriceList(param.getSourceAppId(), hmeinService.parseHotelId(param.getHotelId()),
                        param.getRoomTypeCode(), (String) JsonUtil.toMap(param.getExtra()).get("memberNo"), param.getBeginDate(), checkOutString);
                // 价格校验
                BigDecimal totalPriceHmein = BigDecimal.ZERO;
                BigDecimal raisedTotalPriceHmein = BigDecimal.valueOf(0);
                for (CheckAvailableResult.DailyRate rate : checkAvailableResult.getDailyRate()) {
                    // 筛选当天门市价房态信息
                    RoomStatusResult.RoomRateDetailDailys roomRateDetailDailys = retailPriceList.stream()
                            .filter(roomPrice -> hmeinService.getTime(roomPrice.getStDate()).equals(hmeinService.getTime(rate.getStDate())))
                            .findFirst().orElse(new RoomStatusResult.RoomRateDetailDailys());


                    // 填充实时价格
                    priceCalendarBeanList.add(Route2SourceCheckPriceAndCountResult.PriceCalendarBean.builder()
                            .effectDate(hmeinService.getTime(rate.getStDate()))
                            .quota(Integer.parseInt(rate.getQty()))
                            .retailPrice(roomRateDetailDailys.getPrs1())
                            .purchasePrice(rate.getPrice())
                            .build());

                    totalPriceHmein = totalPriceHmein.add(rate.getPrice());
                    raisedTotalPriceHmein = raisedTotalPriceHmein.add(param.getRaiseFunc().apply(rate.getPrice()));
                }
                if (param.getTotalPrice().compareTo(totalPriceHmein.multiply(BigDecimal.valueOf(param.getRoomCount()))
                        .subtract(param.getTolerancePrice())) < 0) {
                    log.error("订单销售价不能低于采购总价，订单销售价={}，采购总价={}, 容差金额={}",
                            param.getTotalPrice(),
                            totalPriceHmein.multiply(BigDecimal.valueOf(param.getRoomCount())),
                            param.getTolerancePrice());

                    failFlag = true;
                    errorMsg = "房价变动";
                }

                break;
            case CNBEINT:
                /**
                 *  房间数和总价格在接口请求中已校验
                 *  目前美元流程
                 */
                IdentityInfoDTO infoDTO1 = IdentityInfoDTO.builder()
                        .appId(param.getSourceAppId())
                        .securityKey(param.getSourceSecret())
                        .userName((String) JsonUtil.toMap(param.getExtra()).get("userName"))
                        .passWord((String) JsonUtil.toMap(param.getExtra()).get("passWord"))
                        .signature((String) JsonUtil.toMap(param.getExtra()).get("signature"))
                        .build();
                List<HtPriceCalendarCnbe> htPriceCalendarCnbeints = Optional.ofNullable(
                        htPriceCalendarCnbeService.list(new LambdaQueryWrapper<HtPriceCalendarCnbe>()
                                .eq(HtPriceCalendarCnbe::getHotelId, param.getHotelId())
                                .eq(HtPriceCalendarCnbe::getRoomTypeCode, param.getRoomTypeCode())
                        ))
                        .orElse(new ArrayList<>());
                if (CollectionUtils.isEmpty(htPriceCalendarCnbeints)) {
                    throw new RuntimeException("内部错误");
                }
                // 筛选本地价库，统计总价格传入
                BigDecimal sumPriceCnbeint = htPriceCalendarCnbeints.stream()
                        .filter(htPriceCalendarCnbe -> new SimpleDateFormat("yyyy-MM-dd").format(htPriceCalendarCnbe.getCalDate()).compareTo(param.getBeginDate()) >= 0
                                && new SimpleDateFormat("yyyy-MM-dd").format(htPriceCalendarCnbe.getCalDate()).compareTo(checkOutString) < 0)
                        .map(HtPriceCalendarCnbe::getPurchasePrice)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);

                ValiadRoomStatusResp.ValiadRoomStatusInfo valiadRoomStatusInfo1 = cnBookingService.valiadRoomstatus(cnBookingService.parseHotelId(param.getHotelId()),
                        param.getRoomTypeCode(),
                        htPriceCalendarCnbeints.get(0).getProductId(),
                        Integer.toString(param.getRoomCount()),
                        param.getBeginDate(),
                        checkOutString,
                        "USD",
                        sumPriceCnbeint.toString(),
                        infoDTO1);
                if (StringUtils.isBlank(valiadRoomStatusInfo1.getReturnCode())
                        || !"31002".equals(valiadRoomStatusInfo1.getReturnCode())) {
                    throw new RuntimeException("下单校验失败，失败原因：" + valiadRoomStatusInfo1.getReturnMessage());
                }
                // 容差校验判断
                BigDecimal totalPriceCnbeint = BigDecimal.ZERO;
                BigDecimal raisedTotalPriceCnbeint = BigDecimal.valueOf(0);
                for (ValiadRoomStatusResp.PriceAndStatu priceAndStatut : valiadRoomStatusInfo1.getPriceAndStatus().getPriceAndStatu()) {
                    totalPriceCnbeint = totalPriceCnbeint.add(new BigDecimal(priceAndStatut.getPrice()));
                    raisedTotalPriceCnbeint =
                            raisedTotalPriceCnbeint.add(param.getRaiseFunc()
                                    .apply(new BigDecimal(priceAndStatut.getPrice())));
                }

                if (Objects.nonNull(param.getTotalPrice()) && Objects.nonNull(param.getRoomCount())
                        && param.getTotalPrice().compareTo(totalPriceCnbeint.multiply(BigDecimal.valueOf(param.getRoomCount()))
                        .subtract(param.getTolerancePrice())) < 0) {
                    log.error("订单销售价不能低于采购总价，订单销售价={}，采购总价={}, 容差金额={}",
                            param.getTotalPrice(), totalPriceCnbeint.multiply(BigDecimal.valueOf(param.getRoomCount()))
                            , param.getTolerancePrice());
                    errorMsg = "房价变动";
                    failFlag = true;
                }

                break;
            case CNBE:
                /**
                 *  房间数和总价格在接口请求中已校验
                 */
                IdentityInfoDTO infoDTO = IdentityInfoDTO.builder()
                        .appId(param.getSourceAppId())
                        .securityKey(param.getSourceSecret())
                        .userName((String) JsonUtil.toMap(param.getExtra()).get("userName"))
                        .passWord((String) JsonUtil.toMap(param.getExtra()).get("passWord"))
                        .signature((String) JsonUtil.toMap(param.getExtra()).get("signature"))
                        .build();
                List<HtPriceCalendarCnbe> htPriceCalendarCnbes = Optional.ofNullable(
                        htPriceCalendarCnbeService.list(new LambdaQueryWrapper<HtPriceCalendarCnbe>()
                                .eq(HtPriceCalendarCnbe::getHotelId, param.getHotelId())
                                .eq(HtPriceCalendarCnbe::getRoomTypeCode, param.getRoomTypeCode())
                        ))
                        .orElse(new ArrayList<>());
                if (CollectionUtils.isEmpty(htPriceCalendarCnbes)) {
                    throw new RuntimeException("内部错误");
                }
                // 筛选本地价库，统计总价格传入
                BigDecimal sumPriceCnbe = htPriceCalendarCnbes.stream()
                        .filter(htPriceCalendarCnbe -> new SimpleDateFormat("yyyy-MM-dd").format(htPriceCalendarCnbe.getCalDate()).compareTo(param.getBeginDate()) >= 0
                                && new SimpleDateFormat("yyyy-MM-dd").format(htPriceCalendarCnbe.getCalDate()).compareTo(checkOutString) < 0)
                        .map(HtPriceCalendarCnbe::getPurchasePrice)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);

                ValiadRoomStatusResp.ValiadRoomStatusInfo valiadRoomStatusInfo = cnBookingService.valiadRoomstatus(cnBookingService.parseHotelId(param.getHotelId()),
                        param.getRoomTypeCode(),
                        htPriceCalendarCnbes.get(0).getProductId(),
                        Integer.toString(param.getRoomCount()),
                        param.getBeginDate(),
                        checkOutString,
                        "CNY",
                        sumPriceCnbe.toString(),
                        infoDTO);
                if (StringUtils.isBlank(valiadRoomStatusInfo.getReturnCode())
                        || !"31002".equals(valiadRoomStatusInfo.getReturnCode())) {
                    throw new RuntimeException("下单校验失败，失败原因：" + valiadRoomStatusInfo.getReturnMessage());
                }

                // 容差校验判断
                BigDecimal totalPriceCnbe = BigDecimal.ZERO;
                BigDecimal raisedTotalPriceCnbe = BigDecimal.valueOf(0);
                for (ValiadRoomStatusResp.PriceAndStatu priceAndStatu : valiadRoomStatusInfo.getPriceAndStatus().getPriceAndStatu()) {
                    totalPriceCnbe = totalPriceCnbe.add(new BigDecimal(priceAndStatu.getPrice()));
                    raisedTotalPriceCnbe =
                            raisedTotalPriceCnbe.add(param.getRaiseFunc()
                                    .apply(PriceUtil.fen2yuan(Integer.valueOf(priceAndStatu.getPrice()))));
                }

                if (Objects.nonNull(param.getTotalPrice()) && Objects.nonNull(param.getRoomCount())
                        && param.getTotalPrice().compareTo(totalPriceCnbe.multiply(BigDecimal.valueOf(param.getRoomCount()))
                        .subtract(param.getTolerancePrice())) < 0) {
                    log.error("订单销售价不能低于采购总价，订单销售价={}，采购总价={}, 容差金额={}",
                            param.getTotalPrice(), totalPriceCnbe.multiply(BigDecimal.valueOf(param.getRoomCount()))
                            , param.getTolerancePrice());
                    errorMsg = "房价变动";
                    failFlag = true;
                }

                break;
            // REZENCO三方和REZEN二方 ，处理差个companyId
            case REZENCO:
            case REZEN:
                /**
                 *  房间数和价格在接口请求中已校验
                 */
                // 遍历每一天的价格
                List<PostOrderCheckReq.DailyRateList> dailyRateList = new ArrayList<>();
                Long productId = Long.valueOf(rezenService.getProductId(param.getHotelId(),
                        param.getRoomTypeCode(), param.getSourceId(),
                        param.getBreakfastCount(), 4, param.getBeginDate()));

                // 区分二方酒店和三方酒店
                Pattern compile = Pattern.compile("\\d+");
                Matcher matcher = compile.matcher(param.getHotelId());
                Long hotelId = null;
                String innId = null;
                if (matcher.find()) {
                    hotelId = Long.valueOf(matcher.group());
                } else {
                    throw new RuntimeException("匹配酒店Id为空");
                }
                if (rezenService.checkSourceIdIs2(param.getSourceId())) {
                    innId = rezenService.parseInnId(hotelId);
                } else {
                    innId = rezenService.parseInnId3(hotelId);
                }

                for (int i = 0; i < param.getDays(); ++i) {
                    Date nextDate = DateUtils.addDays(DateUtil.parseDate(param.getBeginDate(), "yyyy-MM-dd"), i);
                    String nextDay = new SimpleDateFormat("yyyy-MM-dd").format(nextDate);
                    // 查找对应的房态信息
                    HtPriceCalendarRezen htPriceCalendarRezen = htPriceCalendarRezenService.getBaseMapper()
                            .selectOne(new LambdaQueryWrapper<HtPriceCalendarRezen>()
                                    .eq(HtPriceCalendarRezen::getHotelId, innId)
                                    .eq(HtPriceCalendarRezen::getRoomTypeCode, param.getRoomTypeCode())
                                    .eq(HtPriceCalendarRezen::getCalDate, nextDay)
                                    .eq(HtPriceCalendarRezen::getProductId, productId)
                                    .eq(HtPriceCalendarRezen::getSourceId, param.getSourceId()));
                    PostOrderCheckReq.DailyRateList dailyRate = new PostOrderCheckReq.DailyRateList();
                    // 注意价格转分校验
                    dailyRate.setRoomPrice(PriceUtil.yuan2fen(htPriceCalendarRezen.getPurchasePrice()).intValue());
                    dailyRate.setEffectDate(nextDay);
                    dailyRateList.add(dailyRate);
                }
                PostOrderCheckReq postOrderCheckReq = PostOrderCheckReq.builder()
                        .checkInDate(param.getBeginDate())
                        .checkOutDate(checkOutString)
                        .hotelId(hotelId)
                        .dailyRateList(dailyRateList)
                        .groupId(Long.valueOf((String) JsonUtil.toMap(param.getExtra()).get("groupId")))
                        .numberOfPerson(String.valueOf(param.getOccupancy()))
                        .productId(productId)
                        .roomQuantity(param.getRoomCount())
                        .build();
                // 如果是三方的，则添加公司id
                if (innId.startsWith("REZENCO")) {
                    postOrderCheckReq.setCompanyId(Long.valueOf((String) JsonUtil.toMap(param.getExtra()).get("companyId")));
                }
                RezenBaseResp<List<PostOrderCheckDTO>> listRezenBaseResp = rezenService.checkPriceAndCount(postOrderCheckReq, param.getSourceAppId(), param.getSourceSecret());
                if (listRezenBaseResp.isFail()) {
                    throw new RuntimeException("下单校验失败，失败原因：" + listRezenBaseResp.getRetdesc());
                }

                // 容差校验判断
                BigDecimal totalPriceRezen = BigDecimal.ZERO;
                BigDecimal raisedTotalPriceRezen = BigDecimal.valueOf(0);
                for (PostOrderCheckDTO postOrderCheckDTO : listRezenBaseResp.getBody()) {
                    totalPriceRezen = totalPriceRezen.add(BigDecimal.valueOf((long) postOrderCheckDTO.getRoomPrice() * param.getRoomCount()));
                    raisedTotalPriceRezen =
                            raisedTotalPriceRezen.add(param.getRaiseFunc()
                                    .apply(PriceUtil.fen2yuan(postOrderCheckDTO.getRoomPrice())));
                }

                if (param.getTotalPrice().compareTo(raisedTotalPriceRezen.multiply(BigDecimal.valueOf(param.getRoomCount()))
                        .subtract(param.getTolerancePrice())) < 0) {
                    log.error("订单销售价不能低于采购总价，订单销售价={}，采购总价={}, 容差金额={}",
                            param.getTotalPrice(), raisedTotalPriceRezen.multiply(BigDecimal.valueOf(param.getRoomCount()))
                            , param.getTolerancePrice());
                    errorMsg = "房价变动";
                    failFlag = true;
                }
                break;
            case GREENTREE:
                /**
                 *  房间数在接口请求中已校验,价格未校验
                 */
                // 活动价价格校验
                if ((Boolean) JsonUtil.toMap(param.getExtra()).get("activityFlag")) {
                    Date calDate = null;
                    try {
                        calDate = new SimpleDateFormat("yyyy-MM-dd").parse(param.getBeginDate());
                    } catch (Exception e) {
                        throw new RuntimeException("日期格式化失败");
                    }
                    // 获得房态活动码
                    HtPriceCalendarGreentree htPriceCalendarGreentree = htPriceCalendarGreentreeService.getBaseMapper()
                            .selectOne(new LambdaQueryWrapper<HtPriceCalendarGreentree>()
                                    .eq(HtPriceCalendarGreentree::getSourceId, param.getSourceId())
                                    .eq(HtPriceCalendarGreentree::getHotelId, param.getHotelId())
                                    .eq(HtPriceCalendarGreentree::getRoomTypeCode, param.getRoomTypeCode())
                                    .eq(HtPriceCalendarGreentree::getCalDate, calDate));

                    BookingCheckActivityReq bookingCheckAgreementReq = BookingCheckActivityReq.builder()
                            .startDate(param.getBeginDate())
                            .endDate(checkOutString)
                            .hotelCode(greenTreeService.parseHotelId(param.getHotelId()))
                            .reqRooms(BookingCheckActivityReq.ReqRooms.builder()
                                    .reqRoom(BookingCheckActivityReq.ReqRooms.ReqRoom.builder()
                                            .roomCount(param.getRoomCount())
                                            .roomTypeCode(param.getRoomTypeCode())
                                            .activityCode(htPriceCalendarGreentree.getRateplanId())
                                            .build())
                                    .build())
                            .build();
                    BookingCheckActivityResp bookingCheckActivityResp = greenTreeService.bookingCheckActivity(bookingCheckAgreementReq);
                    // 加价后总价
                    BigDecimal raisedTotalPriceGreentree = BigDecimal.valueOf(0);
                    // 房间多天总价格
                    BigDecimal totalRateGreentree = BigDecimal.ZERO;
                    List<BookingCheckActivityResp.ReqRooms.ReqDate.ReqRoom.RoomRate> roomRateLists = bookingCheckActivityResp.getReqRooms().getReqDate()
                            .stream().map(e -> e.getReqRoom().getRoomRate()).collect(Collectors.toList());
                    for (BookingCheckActivityResp.ReqRooms.ReqDate.ReqRoom.RoomRate roomRate : roomRateLists) {
                        raisedTotalPriceGreentree = raisedTotalPriceGreentree.add(
                                param.getRaiseFunc().apply(roomRate.getPrice()));
                        totalRateGreentree = totalRateGreentree.add(roomRate.getPrice());
                    }
                    // 房间数量
                    Integer roomCount = param.getRoomCount();
                    if (param.getTotalPrice().compareTo(totalRateGreentree.multiply(BigDecimal.valueOf(roomCount))
                            .subtract(param.getTolerancePrice())) < 0) {
                        log.error("订单销售价不能低于采购总价，订单销售价={}，采购总价={}, 容差金额={}",
                                param.getTotalPrice(), totalRateGreentree.multiply(BigDecimal.valueOf(roomCount))
                                , param.getTolerancePrice());
                        errorMsg = "房价变动";
                        failFlag = true;
                    }
                } else {
                    // 协议价价格校验
                    BookingCheckAgreementReq bookingCheckAgreementReq = BookingCheckAgreementReq.builder()
                            .agentAgreementNo((String) JsonUtil.toMap(param.getExtra()).get("agentAgreementNo"))
                            .startDate(param.getBeginDate())
                            .endDate(checkOutString)
                            .hotelCode(greenTreeService.parseHotelId(param.getHotelId()))
                            .reqRooms(BookingCheckAgreementReq.ReqRooms.builder()
                                    .reqRoom(BookingCheckAgreementReq.ReqRooms.ReqRoom.builder()
                                            .roomCount(param.getRoomCount())
                                            .roomTypeCode(param.getRoomTypeCode())
                                            .build())
                                    .build())
                            .build();
                    BookingCheckAgreementResp bookingCheckAgreementResp = greenTreeService.bookingCheckAgreement(bookingCheckAgreementReq);
                    // 加价后总价
                    BigDecimal raisedTotalPriceGreentree = BigDecimal.valueOf(0);
                    // 房间多天总价格
                    BigDecimal totalRateGreentree = BigDecimal.ZERO;
                    List<BookingCheckAgreementResp.ReqRooms.ReqDate.ReqRoom.AgreementRate> roomRateLists = bookingCheckAgreementResp.getReqRooms().getReqDate()
                            .stream().map(e -> e.getReqRoom().getAgreementRate()).collect(Collectors.toList());
                    for (BookingCheckAgreementResp.ReqRooms.ReqDate.ReqRoom.AgreementRate roomRate : roomRateLists) {
                        raisedTotalPriceGreentree = raisedTotalPriceGreentree.add(
                                param.getRaiseFunc().apply(roomRate.getPrice()));
                        totalRateGreentree = totalRateGreentree.add(roomRate.getPrice());
                    }
                    // 房间数量
                    Integer roomCount = param.getRoomCount();
                    if (param.getTotalPrice().compareTo(totalRateGreentree.multiply(BigDecimal.valueOf(roomCount))
                            .subtract(param.getTolerancePrice())) < 0) {
                        log.error("订单销售价不能低于采购总价，订单销售价={}，采购总价={}, 容差金额={}",
                                param.getTotalPrice(), totalRateGreentree.multiply(BigDecimal.valueOf(roomCount))
                                , param.getTolerancePrice());
                        errorMsg = "房价变动";
                        failFlag = true;
                    }
                }

                break;
            default:
                throw new RuntimeException("无效的sourceCode=" + param.getSourceCode());
        }
        return Route2SourceCheckPriceAndCountResult.builder()
                .fail(failFlag)
                .errormsg(errorMsg)
                .priceCalendarBeanList(priceCalendarBeanList)
                .build();
    }
}
